home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 5 / UNZIP_1 / ORIGINAL.C < prev    next >
Text File  |  1992-07-19  |  25KB  |  1,080 lines

  1. #define ATARI_ST 1
  2.  
  3. /*
  4.  * Copyright 1989 Samuel H. Smith;  All rights reserved
  5.  *
  6.  * Do not distribute modified versions without my permission.
  7.  * Do not remove or alter this notice or any other copyright notice.
  8.  * If you use this in your own program you must distribute source code.
  9.  * Do not use any of this in a commercial product.
  10.  *
  11.  */
  12.  
  13. /*
  14.  * UnZip - A simple zipfile extract utility
  15.  *
  16.  * To compile:
  17.  *      tcc -B -O -Z -G -mc unzip.c        ;turbo C 2.0, compact model
  18.  *
  19.  */
  20.  
  21. #define CODE_VERSION  "UnZip:  Zipfile Extract v1.2 of 03-15-89;  (C) 1989 Samuel H. Smith"
  22. #define PRG_VERSION   "\
  23. UnZip:  Atari ST Zipfile Extract v1.2 of 03-30-89\n\
  24. Ported to the Atari ST by Darin Wayrynen.\n\
  25. Derived from code Copyrighted (c)1989 by S.H.Smith"
  26.  
  27. typedef unsigned char byte;    /* code assumes UNSIGNED bytes */
  28. typedef long longint;
  29. typedef unsigned word;
  30. typedef char boolean;
  31.  
  32. #define STRSIZ 256
  33.  
  34. #include <stdio.h>
  35.  /* this is your standard header for all C compiles */
  36.  
  37. #ifndef ATARI_ST
  38. #include <stdlib.h>
  39.  /* this include defines various standard library prototypes */
  40. #else
  41. long buffer_size,in_size,out_size;
  42. #endif
  43.  
  44. /*
  45.  * SEE HOST OPERATING SYSTEM SPECIFICS SECTION STARTING NEAR LINE 180
  46.  *
  47.  */
  48.  
  49.  
  50. /* ----------------------------------------------------------- */
  51. /*
  52.  * Zipfile layout declarations
  53.  *
  54.  */
  55.  
  56. typedef longint signature_type;
  57.  
  58.  
  59. #define LOCAL_FILE_HEADER_SIGNATURE  0x04034b50L
  60.  
  61.  
  62. typedef struct local_file_header {
  63.     word version_needed_to_extract;
  64.     word general_purpose_bit_flag;
  65.     word compression_method;
  66.     word last_mod_file_time;
  67.     word last_mod_file_date;
  68.     longint crc32;
  69.     longint compressed_size;
  70.     longint uncompressed_size;
  71.     word filename_length;
  72.     word extra_field_length;
  73. } local_file_header;
  74.  
  75.  
  76. #define CENTRAL_FILE_HEADER_SIGNATURE  0x02014b50L
  77.  
  78.  
  79. typedef struct central_directory_file_header {
  80.     word version_made_by;
  81.     word version_needed_to_extract;
  82.     word general_purpose_bit_flag;
  83.     word compression_method;
  84.     word last_mod_file_time;
  85.     word last_mod_file_date;
  86.     longint crc32;
  87.     longint compressed_size;
  88.     longint uncompressed_size;
  89.     word filename_length;
  90.     word extra_field_length;
  91.     word file_comment_length;
  92.     word disk_number_start;
  93.     word internal_file_attributes;
  94.     longint external_file_attributes;
  95.     longint relative_offset_local_header;
  96. } central_directory_file_header;
  97.  
  98.  
  99. #define END_CENTRAL_DIR_SIGNATURE  0x06054b50L
  100.  
  101.  
  102. typedef struct end_central_dir_record {
  103.     word number_this_disk;
  104.     word number_disk_with_start_central_directory;
  105.     word total_entries_central_dir_on_this_disk;
  106.     word total_entries_central_dir;
  107.     longint size_central_directory;
  108.     longint offset_start_central_directory;
  109.     word zipfile_comment_length;
  110. } end_central_dir_record;
  111.  
  112.  
  113.  
  114. /* ----------------------------------------------------------- */
  115. /*
  116.  * input file variables
  117.  *
  118.  */
  119.  
  120. #define INBUFSIZ 0x2000L
  121. byte *inbuf;            /* input file buffer - any size is legal */
  122. byte *inptr;
  123.  
  124. int incnt;
  125. unsigned bitbuf;
  126. int bits_left;
  127. boolean zipeof;
  128.  
  129. int zipfd;
  130. char zipfn[STRSIZ];
  131. local_file_header lrec;
  132.  
  133.  
  134. /* ----------------------------------------------------------- */
  135. /*
  136.  * output stream variables
  137.  *
  138.  */
  139.  
  140. #define OUTBUFSIZ 0x6000L
  141. byte *outbuf;                   /* buffer for rle look-back */
  142. byte *outptr;
  143.  
  144. longint outpos;            /* absolute position in outfile */
  145. int outcnt;            /* current position in outbuf */
  146.  
  147. int outfd;
  148. char filename[STRSIZ];
  149. char extra[STRSIZ];
  150.  
  151. #define DLE 144
  152.  
  153.  
  154. /* ----------------------------------------------------------- */
  155. /*
  156.  * shrink/reduce working storage
  157.  *
  158.  */
  159.  
  160. int factor;
  161. byte followers[256][64];
  162. byte Slen[256];
  163.  
  164. #define max_bits 13
  165. #define init_bits 9
  166. #define hsize 8192
  167. #define first_ent 257
  168. #define clear 256
  169.  
  170. typedef int hsize_array_integer[hsize+1];
  171. typedef byte hsize_array_byte[hsize+1];
  172.  
  173. hsize_array_integer prefix_of;
  174. hsize_array_byte suffix_of;
  175. hsize_array_byte stack;
  176.  
  177. int codesize;
  178. int maxcode;
  179. int free_ent;
  180. int maxcodemax;
  181. int offset;
  182. int sizex;
  183.  
  184.  
  185.  
  186. /* ============================================================= */
  187. /*
  188.  * Host operating system details
  189.  *
  190.  */
  191.  
  192. #ifndef ATARI_ST
  193. #include <string.h>
  194. #else
  195. #include <strings.h>
  196. #define strchr index
  197. #endif
  198.  /* this include defines strcpy, strcmp, etc. */
  199.  
  200. #ifndef ATARI_ST
  201. #include <io.h>
  202.  /*
  203.   * this include file defines
  204.   *             struct ftime ...        (* file time/date stamp info *)
  205.   *             int setftime (int handle, struct ftime *ftimep);
  206.   *             #define SEEK_CUR  1     (* lseek() modes *)
  207.   *             #define SEEK_END  2
  208.   *             #define SEEK_SET  0
  209.   */
  210. #else
  211. #define SEEK_CUR  1     (* lseek() modes *)
  212. #define SEEK_END  2
  213. #define SEEK_SET  0
  214. #endif
  215.  
  216.  
  217. #include <fcntl.h>
  218.  /*
  219.   * this include file defines
  220.   *             #define O_BINARY 0x8000  (* no cr-lf translation *)
  221.   * as used in the open() standard function
  222.   */
  223.  
  224. #ifndef ATARI_ST
  225. #include <sys/stat.h>
  226.  /*
  227.   * this include file defines
  228.   *             #define S_IREAD 0x0100  (* owner may read *)
  229.   *             #define S_IWRITE 0x0080 (* owner may write *)
  230.   * as used in the creat() standard function
  231.   */
  232. #endif
  233.  
  234. #ifdef ATARI_ST
  235. #define HIGH_LOW 1
  236. #include <osbind.h>
  237. typedef struct _dt {                    /* My creation! DAW */
  238.     unsigned realdate;
  239.     unsigned realtime;
  240. } dt;
  241. #endif
  242.  
  243.  /*
  244.   * change 'undef' to 'define' if your machine stores high order bytes in
  245.   * lower addresses.
  246.   */
  247.  
  248. #ifndef ATARI_ST
  249. void set_file_time()
  250.  /*
  251.   * set the output file date/time stamp according to information from the
  252.   * zipfile directory record for this file 
  253.   */
  254. {
  255.     union {
  256.                 dt ft;        /* system file time record */
  257.         struct {
  258.                         word ztime;     /* date and time words */
  259.                         word zdate;     /* .. same format as in .ZIP file */
  260.         } zt;
  261.     } td;
  262.  
  263.     /*
  264.      * set output file date and time - this is optional and can be
  265.      * deleted if your compiler does not easily support setftime() 
  266.      */
  267.  
  268.     td.zt.ztime = lrec.last_mod_file_time;
  269.     td.zt.zdate = lrec.last_mod_file_date;
  270.  
  271.     setftime(outfd, &td.ft);
  272. }
  273. #else
  274. #define set_file_time() ;
  275. #endif
  276.  
  277.  
  278. int create_output_file()
  279.  /* return non-0 if creat failed */
  280. {
  281.     /* create the output file with READ and WRITE permissions */
  282. #ifndef ATARI_ST
  283.     outfd = creat(filename, S_IWRITE | S_IREAD);
  284. #else
  285.     outfd = open(filename, O_CREAT | O_RDWR| O_BINARY);
  286. #endif
  287.     if (outfd < 1) {
  288.         printf("Can't create output: %s\n", filename);
  289.         return 1;
  290.     }
  291.  
  292.     /*
  293.      * close the newly created file and reopen it in BINARY mode to
  294.      * disable all CR/LF translations 
  295.      */
  296. #ifndef ATARI_ST
  297.     /*
  298.      * Not neccessary with Atari ST.  Just open() in Binary mode.
  299.      */
  300.     close(outfd);
  301.     outfd = open(filename, O_RDWR | O_BINARY);
  302. #endif
  303.  
  304.     /* write a single byte at EOF to pre-allocate the file */
  305.         lseek(outfd, lrec.uncompressed_size - 1L, SEEK_SET);
  306.     write(outfd, "?", 1);
  307.     lseek(outfd, 0L, SEEK_SET);
  308.     return 0;
  309. }
  310.  
  311.  
  312. int open_input_file()
  313.  /* return non-0 if creat failed */
  314. {
  315.     /*
  316.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  317.      * translation, which would corrupt the bitstreams 
  318.      */
  319.  
  320.     zipfd = open(zipfn, O_RDONLY | O_BINARY);
  321.     if (zipfd < 1) {
  322.         printf("Can't open input file: %s\n", zipfn);
  323.         return (1);
  324.     }
  325.     return 0;
  326. }
  327.  
  328.  
  329. #ifdef HIGH_LOW
  330.  
  331. void swap_bytes(wordp)
  332. word *wordp;
  333.  /* convert intel style 'short int' variable to host format */
  334. {
  335.     char *charp = (char *) wordp;
  336.     char temp;
  337.  
  338.     temp = charp[0];
  339.     charp[0] = charp[1];
  340.     charp[1] = temp;
  341. }
  342.  
  343. void swap_lbytes(longp)
  344. longint *longp;
  345.  /* convert intel style 'long' variable to host format */
  346. {
  347.     char *charp = (char *) longp;
  348.     char temp[4];
  349.  
  350.     temp[3] = charp[0];
  351.     temp[2] = charp[1];
  352.     temp[1] = charp[2];
  353.     temp[0] = charp[3];
  354.  
  355.     charp[0] = temp[0];
  356.     charp[1] = temp[1];
  357.     charp[2] = temp[2];
  358.     charp[3] = temp[3];
  359. }
  360.  
  361. #endif
  362.  
  363.  
  364.  
  365. /* ============================================================= */
  366.  
  367. int FillBuffer()
  368.  /* fill input buffer if possible */
  369. {
  370.     int readsize;
  371.  
  372.         if (lrec.compressed_size <= 0)
  373.         return incnt = 0;
  374.  
  375.         if (lrec.compressed_size > in_size)
  376.         readsize = in_size;
  377.     else
  378.                 readsize = (int) lrec.compressed_size;
  379.     incnt = read(zipfd, inbuf, readsize);
  380.  
  381.         lrec.compressed_size -= incnt;
  382.     inptr = inbuf;
  383.     return incnt--;
  384. }
  385.  
  386. int ReadByte(x)
  387. unsigned *x;
  388.  /* read a byte; return 8 if byte available, 0 if not */
  389. {
  390.     if (incnt-- == 0)
  391.         if (FillBuffer() == 0)
  392.             return 0;
  393.  
  394.     *x = *inptr++;
  395.     return 8;
  396. }
  397.  
  398.  
  399. /* ------------------------------------------------------------- */
  400. static unsigned mask_bits[] =
  401.         {0,     0x0001, 0x0003, 0x0007, 0x000f,
  402.                 0x001f, 0x003f, 0x007f, 0x00ff,
  403.                 0x01ff, 0x03ff, 0x07ff, 0x0fff,
  404.                 0x1fff, 0x3fff, 0x7fff, 0xffff
  405.         };
  406.  
  407.  
  408. int FillBitBuffer(bits)
  409. register int bits;
  410. {
  411.     /* get the bits that are left and read the next word */
  412.     unsigned temp;
  413.         register int result = bitbuf;
  414.     int sbits = bits_left;
  415.     bits -= bits_left;
  416.  
  417.     /* read next word of input */
  418.     bits_left = ReadByte(&bitbuf);
  419.     bits_left += ReadByte(&temp);
  420.     bitbuf |= (temp << 8);
  421.     if (bits_left == 0)
  422.         zipeof = 1;
  423.  
  424.     /* get the remaining bits */
  425.         result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
  426.         bitbuf >>= bits;
  427.         bits_left -= bits;
  428.         return result;
  429. }
  430.  
  431. #define READBIT(nbits,zdest) { if (nbits <= bits_left) { zdest = (int)(bitbuf & mask_bits[nbits]); bitbuf >>= nbits; bits_left -= nbits; } else zdest = FillBitBuffer(nbits);}
  432.  
  433. /*
  434.  * macro READBIT(nbits,zdest)
  435.  *  {
  436.  *      if (nbits <= bits_left) {
  437.  *          zdest = (int)(bitbuf & mask_bits[nbits]);
  438.  *          bitbuf >>= nbits;
  439.  *          bits_left -= nbits;
  440.  *      } else
  441.  *          zdest = FillBitBuffer(nbits);
  442.  *  }
  443.  *
  444.  */
  445.  
  446.  
  447. /* ------------------------------------------------------------- */
  448.  
  449. #include "crc32.h"
  450.  
  451.  
  452. /* ------------------------------------------------------------- */
  453.  
  454. void FlushOutput()
  455.  /* flush contents of output buffer */
  456. {
  457.     UpdateCRC(outbuf, outcnt);
  458.     write(outfd, outbuf, outcnt);
  459.     outpos += outcnt;
  460.     outcnt = 0;
  461.     outptr = outbuf;
  462. }
  463.  
  464. #define OUTB(intc) { *outptr++=intc; if (++outcnt==out_size) FlushOutput(); }
  465.  
  466. /*
  467.  *  macro OUTB(intc)
  468.  *  {
  469.  *      *outptr++=intc;
  470.  *      if (++outcnt==out_size)
  471.  *          FlushOutput();
  472.  *  }
  473.  *
  474.  */
  475.  
  476.  
  477. /* ----------------------------------------------------------- */
  478.  
  479. void LoadFollowers()
  480. {
  481.         register int x;
  482.         register int i;
  483.  
  484.     for (x = 255; x >= 0; x--) {
  485.                 READBIT(6,Slen[x]);
  486.         for (i = 0; i < Slen[x]; i++) {
  487.                         READBIT(8,followers[x][i]);
  488.         }
  489.     }
  490. }
  491.  
  492.  
  493. /* ----------------------------------------------------------- */
  494. /*
  495.  * The Reducing algorithm is actually a combination of two
  496.  * distinct algorithms.  The first algorithm compresses repeated
  497.  * byte sequences, and the second algorithm takes the compressed
  498.  * stream from the first algorithm and applies a probabilistic
  499.  * compression method.
  500.  */
  501.  
  502. int L_table[] = {0, 0x7f, 0x3f, 0x1f, 0x0f};
  503.  
  504. int D_shift[] = {0, 0x07, 0x06, 0x05, 0x04};
  505. int D_mask[]  = {0, 0x01, 0x03, 0x07, 0x0f};
  506.  
  507. int B_table[] = {8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
  508.          5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
  509.          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  510.          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
  511.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  512.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  513.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  514.          7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  515.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  516.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  517.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  518.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  519.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  520.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  521.          8, 8, 8, 8};
  522.  
  523. /* ----------------------------------------------------------- */
  524.  
  525. void unReduce()
  526.  /* expand probablisticly reduced data */
  527. {
  528.         register int lchar;
  529.         register int nchar;
  530.         int ExState;
  531.         register int V;
  532.         register int Len;
  533.  
  534.         factor = lrec.compression_method - 1;
  535.     ExState = 0;
  536.     lchar = 0;
  537.     LoadFollowers();
  538.  
  539.         while (((outpos + outcnt) < lrec.uncompressed_size) && (!zipeof)) {
  540.         if (Slen[lchar] == 0)
  541.                         READBIT(8,nchar)      /* ; */
  542.                 else
  543.         {
  544.                         READBIT(1,nchar);
  545.                         if (nchar != 0)
  546.                                 READBIT(8,nchar)      /* ; */
  547.                         else
  548.             {
  549.                                 int follower;
  550.                                 int bitsneeded = B_table[Slen[lchar]];
  551.                                 READBIT(bitsneeded,follower);
  552.                                 nchar = followers[lchar][follower];
  553.             }
  554.         }
  555.  
  556.         /* expand the resulting byte */
  557.         switch (ExState) {
  558.  
  559.         case 0:
  560.                         if (nchar != DLE)
  561.                                 OUTB(nchar) /*;*/
  562.             else
  563.                 ExState = 1;
  564.             break;
  565.  
  566.         case 1:
  567.                         if (nchar != 0) {
  568.                                 V = nchar;
  569.                 Len = V & L_table[factor];
  570.                 if (Len == L_table[factor])
  571.                     ExState = 2;
  572.                 else
  573.                     ExState = 3;
  574.             }
  575.             else {
  576.                                 OUTB(DLE);
  577.                 ExState = 0;
  578.             }
  579.             break;
  580.  
  581.                 case 2: {
  582.                                 Len += nchar;
  583.                 ExState = 3;
  584.             }
  585.             break;
  586.  
  587.                 case 3: {
  588.                 register int i = Len + 3;
  589.                 int offset = (((V >> D_shift[factor]) &
  590.                                           D_mask[factor]) << 8) + nchar + 1;
  591.                 longint op = outpos + outcnt - offset;
  592.  
  593.                 /* special case- before start of file */
  594.                 while ((op < 0L) && (i > 0)) {
  595.                     OUTB(0);
  596.                     op++;
  597.                     i--;
  598.                 }
  599.  
  600.                 /* normal copy of data from output buffer */
  601.                 {
  602.                     register int ix = (int) (op % out_size);
  603.  
  604.                                         /* do a block memory copy if possible */
  605.                                         if ( ((ix    +i) < out_size) &&
  606.                                              ((outcnt+i) < out_size) ) {
  607.                                                 memcpy(outptr,&outbuf[ix],i);
  608.                                                 outptr += i;
  609.                                                 outcnt += i;
  610.                                         }
  611.  
  612.                                         /* otherwise copy byte by byte */
  613.                                         else while (i--) {
  614.                                                 OUTB(outbuf[ix]);
  615.                                                 if (++ix >= out_size)
  616.                                                         ix = 0;
  617.                                         }
  618.                                 }
  619.  
  620.                 ExState = 0;
  621.             }
  622.             break;
  623.         }
  624.  
  625.                 /* store character for next iteration */
  626.                 lchar = nchar;
  627.         }
  628. }
  629.  
  630.  
  631. /* ------------------------------------------------------------- */
  632. /*
  633.  * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
  634.  * with partial clearing.
  635.  *
  636.  */
  637.  
  638. void partial_clear()
  639. {
  640.         register int pr;
  641.         register int cd;
  642.  
  643.     /* mark all nodes as potentially unused */
  644.     for (cd = first_ent; cd < free_ent; cd++)
  645.         prefix_of[cd] |= 0x8000;
  646.  
  647.     /* unmark those that are used by other nodes */
  648.     for (cd = first_ent; cd < free_ent; cd++) {
  649.         pr = prefix_of[cd] & 0x7fff;    /* reference to another node? */
  650.                 if (pr >= first_ent)            /* flag node as referenced */
  651.             prefix_of[pr] &= 0x7fff;
  652.     }
  653.  
  654.     /* clear the ones that are still marked */
  655.     for (cd = first_ent; cd < free_ent; cd++)
  656.         if ((prefix_of[cd] & 0x8000) != 0)
  657.             prefix_of[cd] = -1;
  658.  
  659.     /* find first cleared node as next free_ent */
  660.         cd = first_ent;
  661.         while ((cd < maxcodemax) && (prefix_of[cd] != -1))
  662.                 cd++;
  663.         free_ent = cd;
  664. }
  665.  
  666.  
  667. /* ------------------------------------------------------------- */
  668.  
  669. void unShrink()
  670. {
  671.         #define  GetCode(dest) READBIT(codesize,dest)
  672.  
  673.     register int code;
  674.     register int stackp;
  675.     int finchar;
  676.     int oldcode;
  677.     int incode;
  678.  
  679.  
  680.     /* decompress the file */
  681.     maxcodemax = 1 << max_bits;
  682.     codesize = init_bits;
  683.     maxcode = (1 << codesize) - 1;
  684.     free_ent = first_ent;
  685.     offset = 0;
  686.     sizex = 0;
  687.  
  688.     for (code = maxcodemax; code > 255; code--)
  689.         prefix_of[code] = -1;
  690.  
  691.     for (code = 255; code >= 0; code--) {
  692.         prefix_of[code] = 0;
  693.         suffix_of[code] = code;
  694.     }
  695.  
  696.     GetCode(oldcode);
  697.     if (zipeof)
  698.         return;
  699.     finchar = oldcode;
  700.  
  701.         OUTB(finchar);
  702.  
  703.         stackp = hsize;
  704.  
  705.     while (!zipeof) {
  706.         GetCode(code);
  707.         if (zipeof)
  708.             return;
  709.  
  710.         while (code == clear) {
  711.             GetCode(code);
  712.             switch (code) {
  713.  
  714.             case 1:{
  715.                     codesize++;
  716.                     if (codesize == max_bits)
  717.                         maxcode = maxcodemax;
  718.                     else
  719.                         maxcode = (1 << codesize) - 1;
  720.                 }
  721.                 break;
  722.  
  723.             case 2:
  724.                 partial_clear();
  725.                 break;
  726.             }
  727.  
  728.             GetCode(code);
  729.             if (zipeof)
  730.                 return;
  731.         }
  732.  
  733.  
  734.         /* special case for KwKwK string */
  735.         incode = code;
  736.         if (prefix_of[code] == -1) {
  737.                         stack[--stackp] = finchar;
  738.             code = oldcode;
  739.         }
  740.  
  741.  
  742.         /* generate output characters in reverse order */
  743.         while (code >= first_ent) {
  744.                         stack[--stackp] = suffix_of[code];
  745.             code = prefix_of[code];
  746.         }
  747.  
  748.         finchar = suffix_of[code];
  749.                 stack[--stackp] = finchar;
  750.  
  751.  
  752.                 /* and put them out in forward order, block copy */
  753.                 if ((hsize-stackp+outcnt) < out_size) {
  754.                         memcpy(outptr,&stack[stackp],hsize-stackp);
  755.                         outptr += hsize-stackp;
  756.                         outcnt += hsize-stackp;
  757.                         stackp = hsize;
  758.                 }
  759.  
  760.                 /* output byte by byte if we can't go by blocks */
  761.                 else while (stackp < hsize)
  762.                         OUTB(stack[stackp++]);
  763.  
  764.  
  765.         /* generate new entry */
  766.         code = free_ent;
  767.         if (code < maxcodemax) {
  768.             prefix_of[code] = oldcode;
  769.             suffix_of[code] = finchar;
  770.  
  771.             do
  772.                 code++;
  773.             while ((code < maxcodemax) && (prefix_of[code] != -1));
  774.  
  775.             free_ent = code;
  776.         }
  777.  
  778.         /* remember previous code */
  779.         oldcode = incode;
  780.     }
  781.  
  782. }
  783.  
  784.  
  785. /* ---------------------------------------------------------- */
  786.  
  787. void extract_member()
  788. {
  789.     unsigned b;
  790.  
  791.     bits_left = 0;
  792.     bitbuf = 0;
  793.     incnt = 0;
  794.     outpos = 0L;
  795.     outcnt = 0;
  796.     outptr = outbuf;
  797.     zipeof = 0;
  798.     crc32val = 0xFFFFFFFFL;
  799.  
  800.  
  801.     /* create the output file with READ and WRITE permissions */
  802.     if (create_output_file())
  803.         prg_exit(1);
  804.  
  805.         switch (lrec.compression_method) {
  806.  
  807.     case 0:        /* stored */
  808.         {
  809.             printf(" Extracting: %-12s ", filename);
  810.             while (ReadByte(&b))
  811.                 OUTB(b);
  812.         }
  813.         break;
  814.  
  815.         case 1: {
  816.             printf("UnShrinking: %-12s ", filename);
  817.             unShrink();
  818.         }
  819.         break;
  820.  
  821.     case 2:
  822.     case 3:
  823.     case 4:
  824.         case 5: {
  825.             printf("  Expanding: %-12s ", filename);
  826.             unReduce();
  827.         }
  828.         break;
  829.  
  830.     default:
  831.         printf("Unknown compression method.");
  832.     }
  833.  
  834.  
  835.     /* write the last partial buffer, if any */
  836.     if (outcnt > 0) {
  837.         UpdateCRC(outbuf, outcnt);
  838.         write(outfd, outbuf, outcnt);
  839.     }
  840.  
  841.     /* set output file date and time */
  842.     set_file_time();
  843.  
  844.     close(outfd);
  845.  
  846.     crc32val = -1 - crc32val;
  847. #ifdef HIGH_LOW
  848.     swap_lbytes(&lrec.crc32);
  849. #endif
  850.         if (crc32val != lrec.crc32)
  851.                 printf(" Bad CRC %08lx  (should be %08lx)", lrec.crc32, crc32val);
  852.  
  853.     printf("\n");
  854. }
  855.  
  856.  
  857. /* ---------------------------------------------------------- */
  858.  
  859. void get_string(len,s)
  860. int len;
  861. char *s;
  862. {
  863.     read(zipfd, s, len);
  864.     s[len] = 0;
  865. }
  866.  
  867.  
  868. /* ---------------------------------------------------------- */
  869.  
  870. void process_local_file_header()
  871. {
  872.     read(zipfd, &lrec, sizeof(lrec));
  873.  
  874. #ifdef HIGH_LOW
  875.     swap_bytes(&lrec.filename_length);
  876.     swap_bytes(&lrec.extra_field_length);
  877.     swap_lbytes(&lrec.compressed_size);
  878.     swap_lbytes(&lrec.uncompressed_size);
  879.     swap_bytes(&lrec.compression_method);
  880. #endif
  881.  
  882.     get_string(lrec.filename_length, filename);
  883.     get_string(lrec.extra_field_length, extra);
  884.     extract_member();
  885. }
  886.  
  887.  
  888. /* ---------------------------------------------------------- */
  889.  
  890. void process_central_file_header()
  891. {
  892.     central_directory_file_header rec;
  893.     char filename[STRSIZ];
  894.     char extra[STRSIZ];
  895.     char comment[STRSIZ];
  896.  
  897.     read(zipfd, &rec, sizeof(rec));
  898.  
  899. #ifdef HIGH_LOW
  900.     swap_bytes(&rec.filename_length);
  901.     swap_bytes(&rec.extra_field_length);
  902.     swap_bytes(&rec.file_comment_length);
  903. #endif
  904.  
  905.     get_string(rec.filename_length, filename);
  906.     get_string(rec.extra_field_length, extra);
  907.     get_string(rec.file_comment_length, comment);
  908. }
  909.  
  910.  
  911. /* ---------------------------------------------------------- */
  912.  
  913. void process_end_central_dir()
  914. {
  915.     end_central_dir_record rec;
  916.     char comment[STRSIZ];
  917.  
  918.     read(zipfd, &rec, sizeof(rec));
  919.  
  920. #ifdef HIGH_LOW
  921.     swap_bytes(&rec.zipfile_comment_length);
  922. #endif
  923.  
  924.     get_string(rec.zipfile_comment_length, comment);
  925. }
  926.  
  927.  
  928. /* ---------------------------------------------------------- */
  929.  
  930. void process_headers()
  931. {
  932.     longint sig;
  933.  
  934.     while (1) {
  935.         if (read(zipfd, &sig, sizeof(sig)) != sizeof(sig))
  936.             return;
  937.  
  938. #ifdef HIGH_LOW
  939.         swap_lbytes(&sig);
  940. #endif
  941.  
  942.                 if (sig == LOCAL_FILE_HEADER_SIGNATURE)
  943.             process_local_file_header();
  944.                 else if (sig == CENTRAL_FILE_HEADER_SIGNATURE)
  945.             process_central_file_header();
  946.                 else if (sig == END_CENTRAL_DIR_SIGNATURE) {
  947.             process_end_central_dir();
  948.             return;
  949.         }
  950.                 else {
  951.             printf("Invalid Zipfile Header\n");
  952.             return;
  953.         }
  954.     }
  955.  
  956. }
  957.  
  958.  
  959. /* ---------------------------------------------------------- */
  960.  
  961. void extract_zipfile()
  962. {
  963.     /*
  964.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  965.      * translation, which would corrupt the bitstreams 
  966.      */
  967.     
  968.     printf("Buffers - ");
  969.     printf("(input --> %7ld bytes) ",in_size);
  970.     printf("(output --> %7ld bytes)\n\n",out_size);
  971.  
  972.     if (open_input_file())
  973.         prg_exit(1);
  974.  
  975.     process_headers();
  976.  
  977.     close(zipfd);
  978. }
  979.  
  980.  
  981. /* ---------------------------------------------------------- */
  982. /*
  983.  * main program
  984.  *
  985.  */
  986.  
  987. void main(argc,argv)
  988. int argc;
  989. char **argv;
  990. {
  991. #ifdef ATARI_ST
  992.     int buffer_fail = 0;
  993. #endif
  994.  
  995.            printf("\n\n%s\n",PRG_VERSION); 
  996.            printf("Courtesy of:  Darin Wayrynen, S.H.Smith and\n              The Tool Shop BBS,  (602) 279-2673.\n"); 
  997.     if (argc != 2)
  998.     {
  999.         printf("\nYou may copy and distribute this program freely, provided that:\n");
  1000.         printf("    1)   No fee is charged for such copying and distribution, and\n");
  1001.         printf("    2)   It is distributed ONLY in its original, unmodified state.\n\n");
  1002.         printf("If you wish to distribute a modified version of this program, you MUST\n");
  1003.         printf("include the source code.\n\n");
  1004.         printf("If you modify this program, we would appreciate a copy of the  new source\n");
  1005.         printf("code.  Samuel is holding the copyright on the source code, so please don't\n");
  1006.         printf("delete his  name from the program files or from the documentation.\n\n");
  1007.         printf("IN NO EVENT WILL WE BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST\n");
  1008.         printf("PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES\n");
  1009.         printf("ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY\n");
  1010.         printf("CLAIM BY ANY OTHER PARTY.\n\n");
  1011.         printf("Usage:  UnZip FILE[.zip]\n");
  1012. #ifdef ATARI_ST
  1013.         prg_exit(0);
  1014. #else
  1015.         exit(1);
  1016. #endif
  1017.     }
  1018.     printf("\n");
  1019.  
  1020.     /* .ZIP default if none provided by user */
  1021.     strcpy(zipfn, argv[1]);
  1022.     if (strchr(zipfn, '.') == NULL)
  1023.         strcat(zipfn, ".ZIP");
  1024.  
  1025. #ifdef ATARI_ST
  1026.     /* ST buffer allocation */
  1027.     buffer_size = Malloc(-1L)-10000L;              /* returns largest free block */
  1028.     if (buffer_size<(INBUFSIZ + OUTBUFSIZ))
  1029.         buffer_fail=1;
  1030.     in_size = (buffer_size-(INBUFSIZ + OUTBUFSIZ))/100L*55L+INBUFSIZ;
  1031.     out_size = (buffer_size-(INBUFSIZ + OUTBUFSIZ))/100L*35L+OUTBUFSIZ;
  1032.     inbuf = (byte *)Malloc(in_size);         /* 60% */
  1033.     outbuf = (byte *)Malloc(out_size);        /* 40% */
  1034.     if ((inbuf== NULL) || (outbuf == NULL) || buffer_fail)
  1035.     {
  1036.         printf("Can't allocate buffers!\n");
  1037.         prg_exit(1);
  1038.     }
  1039. #else
  1040.         /* allocate i/o buffers */
  1041.     inbuf = (byte *) (malloc(INBUFSIZ));
  1042.     outbuf = (byte *) (malloc(OUTBUFSIZ));
  1043.     if ((inbuf == NULL) || (outbuf == NULL)) {
  1044.         printf("Can't allocate buffers!\n");
  1045.         exit(1);
  1046.     }
  1047. #endif
  1048.         /* do the job... */
  1049.         extract_zipfile();
  1050. #ifdef ATARI_ST
  1051.     prg_exit(0);
  1052. #else
  1053.     exit(0);
  1054. #endif
  1055. }
  1056.  
  1057. prg_exit(value)
  1058. int value;
  1059. {
  1060.     setbuffer(stdout,0L);                         /* turn off printf
  1061.                                                    buffering */
  1062.     printf("\nPress any key to continue.");
  1063.     
  1064.     Bconin(2);                                    /* wait for keypress before
  1065.                                                    exiting, in case prg is
  1066.                                                    run from desktop */
  1067.     printf("\n");
  1068.     exit(value);
  1069. }
  1070.  
  1071. #ifdef ATARI_ST
  1072. memcpy(to,from,count)
  1073. register char *to,*from;
  1074. register unsigned int count;
  1075. {
  1076.     for(;count>0;--count,++to,++from)
  1077.         *to=*from;
  1078. }
  1079. #endif
  1080.